// #include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>
#include <softPwm.h>
// #include <stdint.h>
// #include <stdarg.h>
#ifndef tmodestructok
#define tmodestructok
#define T_STNAMENOTNULL if(name==NULL){return 0;} 
// #define T_GNDISOK if( pinGND!=NULL && pinGND->mode!=INPUT ){return 0;}
#define T_STMODIS(name,x) if(name->mode != x){return 0;}
#define IF_RASPINSTUPOK if(wiringPiSetup()==-1){return 1;}

typedef struct {
    int pin;
    int mode;
    // int power;
} * T_GPIO;

T_GPIO NewT_GPIO(){
    return (T_GPIO)malloc(sizeof(T_GPIO));
}

int InitT_GPIO(T_GPIO name,int Wpin,char *_pinmode){
    T_STNAMENOTNULL
    name->pin=Wpin;
    if(!strcmp(_pinmode,"i")){
        name->mode=INPUT;
        pinMode(name->pin,INPUT);
    }else if(!strcmp(_pinmode,"o")){
        name->mode=OUTPUT;
        pinMode(name->pin,OUTPUT);
    }else if(!strcmp(_pinmode,"po")){
        name->mode=PWM_OUTPUT;
        pinMode(name->pin,PWM_OUTPUT);
    }else if(!strcmp(_pinmode,"c")){
        name->mode=GPIO_CLOCK;
        pinMode(name->pin,GPIO_CLOCK);
    }
    return 1;
}

int InitT_PGPIO(T_GPIO name){
	T_STNAMENOTNULL
	softPwmCreate(name->pin);
}

int ChangeModeT_GPIO(T_GPIO name,char *_pinmode){
    T_STNAMENOTNULL
    if(!strcmp(_pinmode,"i")){
        name->mode=INPUT;
        pinMode(name->pin,INPUT);
    }else if(!strcmp(_pinmode,"o")){
        name->mode=OUTPUT;
        pinMode(name->pin,OUTPUT);
    }else if(!strcmp(_pinmode,"po")){
        name->mode=PWM_OUTPUT;
        pinMode(name->pin,PWM_OUTPUT);
    }else if(!strcmp(_pinmode,"c")){
        name->mode=GPIO_CLOCK;
        pinMode(name->pin,GPIO_CLOCK);
    }
    return 1;
}

int WriteT_GPIO(T_GPIO name,int var){
    T_STNAMENOTNULL
    if(var){
        digitalWrite(name->pin,1);
    }else{
        digitalWrite(name->pin,0);
    }
    return 1;
}

int ReadT_GPIO(T_GPIO name){
    return digitalRead(name->pin);
}

int DeleteT_GPIO(T_GPIO name){
    free(name);
}

// int InitSoftPwm(int pin,int var,int range){
//     pinMode(pin,OUTPUT);
//     softPwmCreate(pin,var,range);
// }

typedef struct {
    T_GPIO S;
    T_GPIO GND;
} *T_LED;

T_LED NewT_LED(){
    T_LED tmp = (T_LED)malloc(sizeof(T_LED));
    tmp->S = NewT_GPIO();
    tmp->GND = NULL;
    return tmp;
}

int InitT_LED(T_LED name,int pinS,int pinGND){
    T_STNAMENOTNULL
    if( pinGND!=-1 ){
        name->GND = NewT_GPIO();
        InitT_GPIO(name->GND,pinGND,"i");
    }
    //name->GND=pinGND;
    InitT_GPIO(name->S,pinS,"o");
    return 1;
}

int LightT_LED(T_LED name){
    T_STNAMENOTNULL
    T_STMODIS(name->S,OUTPUT)
    // printf("aaaa\n");
    if(name->GND!=NULL){
        T_STMODIS(name->GND,INPUT)
    }    
    // printf("bbbbb\n");
    
    // printf("aaaaa\n");
    return WriteT_GPIO(name->S,1);
}

int ShutT_LED(T_LED name){
    T_STNAMENOTNULL
    return WriteT_GPIO(name->S,0);
}

int DeleteT_LED(T_LED name){
    T_STNAMENOTNULL
    DeleteT_GPIO(name->GND);
    DeleteT_GPIO(name->S);
    free(name);
}

typedef struct {
    T_LED R,G;
} *T_DLED;

T_DLED NewT_DLED(){
    T_DLED tmp =(T_DLED)malloc(sizeof(T_DLED));
    tmp->G = NewT_LED();
    tmp->R = NewT_LED();
    return tmp;
}

int InitT_DLED(T_DLED name,int pinG,int pinR,int pinGND){
    T_STNAMENOTNULL
    //T_GNDISOK
    InitT_LED(name->G,pinG,pinGND);
    InitT_LED(name->R,pinR,pinGND);
    return 1;
}

int LightT_DLED(T_DLED name,char *which){
    T_STNAMENOTNULL
    if(!strcmp(which,"R")){
        return LightT_LED(name->R);
    }else if(!strcmp(which,"G")){
        return LightT_LED(name->G);
    }else{
        return 0;
    }
}

int ShutT_DLED(T_DLED name){
    T_STNAMENOTNULL
    int tmp1=0,tmp2=0;
    tmp1 =ShutT_LED(name->G);
    tmp2 =ShutT_LED(name->R);
    return tmp1 || tmp2;
}

int DeleteT_DLED(T_DLED name){
    T_STNAMENOTNULL
    DeleteT_LED(name->G);
    DeleteT_LED(name->R);
    free(name);
}

void T_Wait(unsigned int howLONG){
    delay(howLONG);
}

typedef struct{
    T_LED R,G,B;
} *T_RGBLED;

T_RGBLED NewT_RGBLED(){
    T_RGBLED tmp = (T_RGBLED)malloc(sizeof(T_RGBLED));
    tmp->B=NewT_LED();
    tmp->G=NewT_LED();
    tmp->R=NewT_LED();
    return tmp;
}

int InitT_RGBLED(T_RGBLED name,int R,int G,int B,int GND){
    T_STNAMENOTNULL
    InitT_LED(name->B,B,GND);
    InitT_LED(name->G,G,GND);
    InitT_LED(name->R,R,GND);
    softPwmCreate(R,0,100);
    // printf("%d\n",a);
    softPwmCreate(G,0,100);
    softPwmCreate(B,0,100);
    
    return 1;
}

// int SetColorT_RGBLED(T_RGBLED name,int R,int G,int B){
//     T_STNAMENOTNULL
//     // printf("%daaaaa\n",R);
//     softPwmWrite(name->R->S->pin,R);
//     softPwmWrite(name->G->S->pin,G);
//     softPwmWrite(name->B->S->pin,B);
//     return 1;
// }

int LightT_RGBLED(T_RGBLED name,int R,int G,int B){
    T_STNAMENOTNULL
    // LightT_LED(name->R);
    // LightT_LED(name->G);
    // LightT_LED(name->B);
    softPwmWrite(name->R->S->pin,R);
    softPwmWrite(name->G->S->pin,G);
    softPwmWrite(name->B->S->pin,B);
    return 1;
}

int ShutT_RGBLED(T_RGBLED name){
    T_STNAMENOTNULL
    // ShutT_LED(name->B);
    // ShutT_LED(name->G);
    // ShutT_LED(name->R);
    softPwmStop(name->B->S->pin);
    softPwmStop(name->G->S->pin);
    softPwmStop(name->R->S->pin);
    return 1;
}

int DeleteT_RGBLED(T_RGBLED name){
    T_STNAMENOTNULL
    // softPwmStop(name->B->S->pin);
    // softPwmStop(name->G->S->pin);
    // softPwmStop(name->R->S->pin);
    DeleteT_LED(name->B);
    DeleteT_LED(name->G);
    DeleteT_LED(name->R);
    free(name);
    return 1;
}


#endif
